package edu.dongthang.controller;

import android.accounts.NetworkErrorException;
import android.app.Application;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.StrictMode;
import android.util.Log;
import android.widget.Toast;

import java.net.*;

/**
 * @author thangnd
 * 
 */
public class AppDelegate extends Application {

	public ClientThread client;
	public int mouse_sensitivity = 1;
	public boolean connected = false;
	public boolean network_reachable = true;
	String ipClient;

	public void onCreate() {
		super.onCreate();
		 if( Build.VERSION.SDK_INT >= 9){
	            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
	            StrictMode.setThreadPolicy(policy); 
	     }
		 //-------------------
		 WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
			WifiInfo wifiInfo = wifiManager.getConnectionInfo();

			int ipAddress = wifiInfo.getIpAddress(); // wifiManager.
			

			ipClient = String.format("%d.%d.%d.%d", (ipAddress & 0xff),
					(ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff),
					(ipAddress >> 24 & 0xff));
		//--------------------

	}

	public void createClientThread(String ipAddress, int port) throws NetworkErrorException {
		client = new ClientThread(ipAddress, port);

		Thread cThread = new Thread(client);
		cThread.start();

	}

	public void sendMessage(String message) {
		client.sendMessage(message);
	}
	public void receivNote(){
		client.receiverNote();
	}

//	public String Scan(){
//		return client.autoScan();
//	}
	public void stopServer() {
		if (connected) {
			client.closeSocket();
		}
	}

	// ClientThread Class implementation
	public class ClientThread implements Runnable {

		public InetAddress serverAddr;
		public int serverPort;
		private DatagramSocket socket;
		byte[] buf = new byte[2000];
		byte[] bufnote = new byte[2000];
		InetAddress inetTest;
		//private DatagramPacket buf_note;
		//private byte[] buf_noteslide = new byte[1500];
		String message;

		public ClientThread(String ip, int port) {
			try {
				serverAddr = InetAddress.getByName(ip);
			} catch (Exception e) {
				Log.e("ClientActivity", "C: Error", e);
			}
			serverPort = port;
		}


		// Opens the socket and output buffer to the remote server
		public void run() {
			try {
				socket = new DatagramSocket();
				if (socket != null) {
					socket.setSoTimeout(3000);
					connected = testConnection();
					if (connected)
						surveyConnection();
						//receiverNote();
				}

			} catch (Exception e) {
				Log.e("ClientActivity", "Client Connection Error", e);
			}
		}

		public void sendMessage(String message){
			try {
				buf = message.getBytes();
				if (buf != null) {
					DatagramPacket out = new DatagramPacket(buf, buf.length, serverAddr, serverPort);
					socket.send(out);
					network_reachable = true;
				}

			} catch (Exception e) {
				Log.e("ClientActivity", "Client Send Error:" + serverAddr + serverPort);
				if (e.getMessage().equals("Network unreachable")) {
					Log.e("ClientActivity", "Netork UNREACHABLE!!!!:");
					network_reachable = false;
				}
				//network_reachable = false;
				closeSocketNoMessge();
			}
			

		}
		
		public void closeSocketNoMessge() {
			socket.close();
			connected = false;
		}

		public void closeSocket() {
			sendMessage(new String("Close"));
			socket.close();
			connected = false;
		}

		public void receiverNote() {
			try {
				if(!connected){
					bufnote = new String("note").getBytes();
				}
				else {
					bufnote = new String("send_note").getBytes();
				}
				DatagramPacket out = new DatagramPacket(bufnote, bufnote.length,
						serverAddr, serverPort);
				socket.send(out);
			} catch (Exception e) {
		
			}
			try {
				DatagramPacket buf_note = new DatagramPacket(bufnote,bufnote.length);
				socket.receive(buf_note);
				message = new String(buf_note.getData(), 0,
						buf_note.getLength());
				Log.d("note", message);
			} catch (Exception e) {
				// TODO: handle exception
			}
		
		}


		private boolean testConnection() {
			try {
				if (!connected)
					buf = new String("Connectivity").getBytes();
				else
					buf = new String("connected").getBytes();
				DatagramPacket out = new DatagramPacket(buf, buf.length,
						serverAddr, serverPort);
				socket.send(out);
			} catch (Exception e) {
				return false;
			}

			try {
				DatagramPacket in = new DatagramPacket(buf, buf.length);
				socket.receive(in);
				return true;
			} catch (Exception e) {
				return false;
			}
		}
		
		private String autoScan(){
			String iIPv4 = null;
			String IPv4Start = null;
			iIPv4 = ipClient.substring(0, ipClient.lastIndexOf("."));
		    iIPv4 += ".";
		    
		    for(int i =1; i<255;i++){
		    	try {
		    		IPv4Start = iIPv4 +i;
					inetTest = InetAddress.getByName(IPv4Start);					
				} catch (UnknownHostException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		    	
		    	try {
					if (!connected)
						buf = new String("Connectivity").getBytes();
					else
						buf = new String("connected").getBytes();
					DatagramPacket out = new DatagramPacket(buf, buf.length,
							inetTest, serverPort);
					socket.send(out);
				} catch (Exception e) {
					Log.d("Testing", "Fail");
				}

				try {
					DatagramPacket in = new DatagramPacket(buf, buf.length);
					socket.receive(in);
					//return iIPv4 + i;
				} catch (Exception e) {
					Log.d("Testing", "Fail");
				}
		    }
			return IPv4Start;

		}

		private void surveyConnection() {
			int count = 0;
			while (connected) {
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
				}

				if (!testConnection())
					count++;
				else
					count = 0;

				if (count == 60) {
					closeSocket();
					return;
				}
			}
		}

	}
}
